﻿using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;

namespace MetadataDesignerLibrary
{
    public class AssemblyDefinitionRule : ILRule<AssemblyDefinitionHandle>
    {
        [ILInfo(true)]
        public string Name { get; }

        [ILInfo]
        public Version Version { get; }

        [ILInfo]
        public string Culture { get; }

        [ILInfo]
        public byte[] PublicKey { get; }

        [ILInfo]
        public AssemblyFlags Flags { get; }

        [ILInfo]
        public AssemblyHashAlgorithm HashAlgorithm { get; }

        [ILInfo(true, ILInfoParseMethod.AsString)]
        public AssemblyName AssemblyName { get; }

        [ILInfo(ILInfoParseMethod.AsEntityHandleCollection)]
        public CustomAttributeHandleCollection CustomAttributes { get; }

        [ILInfo(ILInfoParseMethod.AsEntityHandleCollection)]
        public DeclarativeSecurityAttributeHandleCollection DeclarativeSecurityAttributes { get; }

        public AssemblyDefinitionRule(
            string name,
            Version version,
            string culture,
            byte[] publicKey,
            AssemblyFlags flags,
            AssemblyHashAlgorithm hashAlgorithm)
            : base()
        {
            Name = name;
            Version = version;
            Culture = culture;
            PublicKey = publicKey;
            Flags = flags;
            HashAlgorithm = hashAlgorithm;
        }

        public AssemblyDefinitionRule(MetadataReader reader)
            : base(reader)
        {
            AssemblyDefinition assemblyDefinition = reader.GetAssemblyDefinition();
            Culture = reader.GetString(assemblyDefinition.Culture);
            Flags = assemblyDefinition.Flags;
            HashAlgorithm = assemblyDefinition.HashAlgorithm;
            Name = reader.GetString(assemblyDefinition.Name);
            PublicKey = reader.GetBlobBytes(assemblyDefinition.PublicKey);
            Version = assemblyDefinition.Version;
            AssemblyName = assemblyDefinition.GetAssemblyName();
            CustomAttributes = assemblyDefinition.GetCustomAttributes();
            DeclarativeSecurityAttributes = assemblyDefinition.GetDeclarativeSecurityAttributes();
        }

        public override AssemblyDefinitionHandle Write(MetadataDesigner designer)
        {
            MetadataBuilder builder = designer.Builder;
            return builder.AddAssembly(
                name: Name == null ? default : builder.GetOrAddString(Name),
                version: Version,
                culture: Culture == null ? default : builder.GetOrAddString(Culture),
                publicKey: PublicKey == null ? default : builder.GetOrAddBlob(PublicKey),
                flags: Flags,
                hashAlgorithm: HashAlgorithm);
        }
    }
}